// src/lorawan.rs
use aes::Aes128; 
use cmac::{Cmac, Mac, NewMac}; 
use serde::{Deserialize, Serialize}; 
use aes_gcm::aead::{Aead, NewAead};
use aes_gcm::{Aes128Gcm, Key, Nonce};
use base64;
use hex;
use crate::handlers::DeviceParams;

const MIC_SIZE: usize = 4;

#[derive(Debug, Deserialize, Serialize)]
pub struct LoRaWanPacket {
    pub mhdr: u8,         
    pub payload: Vec<u8>, 
    pub mic: [u8; MIC_SIZE],
}

pub fn parse(packet: &[u8]) -> Result<LoRaWanPacket, &'static str> {
    if packet.len() < 5 {
        return Err("Packet too short");
    }

    let mhdr = packet[0];
    let mic_start = packet.len() - MIC_SIZE;
    let payload = packet[1..mic_start].to_vec();
    let mic = packet[mic_start..].try_into().map_err(|_| "MIC extraction failed")?;

    Ok(LoRaWanPacket { mhdr, payload, mic })
}

pub fn verify_mic(packet: &[u8], key: &[u8; 16]) -> Result<bool, &'static str> {
    let mic_start = packet.len() - MIC_SIZE;
    let data = &packet[..mic_start];
    let received_mic = &packet[mic_start..];

    let mut cmac = Cmac::<Aes128>::new_from_slice(key).map_err(|_| "Invalid key length")?;
    cmac.update(data);
    let computed_mic = cmac.finalize().into_bytes();

    Ok(received_mic == &computed_mic[..MIC_SIZE])
}

pub fn convert_to_device_params(packet: LoRaWanPacket) -> Result<DeviceParams, &'static str> {
    match packet.mhdr {
        0x00 => { 
            //消息头字段（MHDR）0x00 表示 Join Request 类型的数据包。
            if packet.payload.len() < 18 {
                return Err("加入请求有效负载长度无效");
            }
            
            let app_eui = hex::encode(&packet.payload[0..8]);
            let dev_eui = hex::encode(&packet.payload[8..16]);
            let dev_nonce = hex::encode(&packet.payload[16..18]);
            println!("app_eui{:?} dev_eui {:?} dev_nonce {}", app_eui, dev_eui,dev_nonce);
            Ok(DeviceParams {
                dev_eui,
                app_eui,
                app_key: "00112233445566778899AABBCCDDEEFF".to_string(),
                dev_nonce,
                dev_addr: "default".to_string(),
                nwk_skey: "default".to_string(),
                app_skey: "default".to_string(),
                join_nonce: "default".to_string(),
            })
        },
        _ => Err("Unsupported MHDR value")
    }
}

pub fn encrypt(data: &[u8], key: &str) -> Result<String, String> {
    let key_bytes = hex::decode(key).map_err(|_| "Invalid key format")?;

    if key_bytes.len() != 16 {
        return Err("Invalid key length".to_string());
    }

    let key = Key::from_slice(&key_bytes);
    let cipher = Aes128Gcm::new(key);
    let nonce = Nonce::from_slice(b"unique nonce");

    let ciphertext = cipher.encrypt(nonce, data).map_err(|_| "Encryption failed")?;
    Ok(base64::encode(&ciphertext))
}
